This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(ggplot2)
library(tidyr)
library(readr)
library(viridis)
library(ggmap)
Google Maps API Terms of Service: http://developers.google.com/maps/terms.
Please cite ggmap if you use it: see citation('ggmap') for details.
library(ggmosaic)
Loading required package: productplots
Attaching package: ‘ggmosaic’
The following objects are masked from ‘package:productplots’:
ddecker, hspine, mosaic, prodcalc, spine, vspine
SFPD <- read_csv("SFPD_Incidents_-_from_1_January_2003.csv",
col_types = cols(Date = col_date(format = "%m/%d/%Y"), Time= col_character()))
SFPD <- SFPD [order(SFPD$Date),]
SFPD <- SFPD %>% filter( Category != 'OTHER OFFENSES' )
SFPD_1 <- SFPD %>% mutate(Year = (format(as.Date(Date, format="%d/%m/%Y"),"%Y")))
SFPD <- SFPD_1 %>% filter( Year != 2017 )
SFPD_top7 <- SFPD %>% filter(Category == 'LARCENY/THEFT'| Category == 'NON-CRIMINAL'| Category == 'ASSAULT'| Category == 'VEHICLE THEFT'| Category == 'DRUG/NARCOTIC'| Category =='VANDALISM'| Category == 'WARRANTS'| Category == 'BURGLARY'| Category =='SUSPICIOUS OCC'| Category =='MISSING PERSON' | Category =='ROBBERY' | Category =='FRAUD' )
SFPD_vehicle_theft <- SFPD_top7 %>% filter(Category == 'VEHICLE THEFT')
SFPD_vehicle_theft <- SFPD_vehicle_theft %>% mutate(Month = (format(as.Date(Date, format="%d/%m/%Y"),"%m")))
SFPD_vehicle_theft <- SFPD_vehicle_theft %>% mutate(date= (format(as.Date(Date, format="%d/%m/%Y"),"%d")))
SFPD_vehicle_theft <- SFPD_vehicle_theft %>% mutate(Hour= format(as.POSIXct(Time,format="%H:%M"),"%H"))
SFPD_VT_oct_ingleside <- SFPD_vehicle_theft %>% filter(Month == 10 & PdDistrict== 'INGLESIDE')
SFPD_VT_oct_ingleside <- SFPD_VT_oct_ingleside %>% mutate(date= (format(as.Date(Date, format="%d/%m/%Y"),"%d")))
SFPD_stolen_vehicle <- SFPD_vehicle_theft %>% filter(Descript=="STOLEN AUTOMOBILE" | Descript=="STOLEN TRAILER" |Descript=="STOLEN TRUCK"|Descript=="STOLEN BUS" |Descript=="STOLEN MISCELLANEOUS VEHICLE" |Descript=="STOLEN MOTORCYCLE")
SFPD_recovered_vehicle <- SFPD_vehicle_theft %>% filter(Descript=="VEHICLE, RECOVERED, BUS" |Descript=="VEHICLE, RECOVERED, CAMPER-HOUSE CAR-MOTOR HOME" |Descript=="RECOVERED VEHICLE - STOLEN OUTSIDE SF" | Descript=="VEHICLE, RECOVERED, MOBILE HOME-TRAILER"|Descript=="VEHICLE, RECOVERED, AUTO" |Descript=="VEHICLE, RECOVERED, MOTORCYCLE" |Descript=="VEHICLE, RECOVERED, OTHER VEHICLE")
SFPD_stolen_outside<- SFPD_vehicle_theft %>% filter(Descript== "RECOVERED VEHICLE - STOLEN OUTSIDE SF" )
SFPD_tampering <- SFPD_vehicle_theft %>% filter(Descript=="TAMPERING WITH A VEHICLE" )
SFPD_stolen_auto <- SFPD_vehicle_theft %>% filter(Descript=="STOLEN AUTOMOBILE"|Descript=="VEHICLE, RECOVERED, AUTO" )
SFPD_stolen_truck <- SFPD_vehicle_theft %>% filter(Descript=="STOLEN TRUCK"|Descript=="VEHICLE, RECOVERED, BUS" )
SFPD_stolen_motorcycle <- SFPD_vehicle_theft %>% filter(Descript=="STOLEN MOTORCYCLE"|Descript=="VEHICLE, RECOVERED, MOTORCYCLE" )
SFPD_stolen_trailer <- SFPD_vehicle_theft %>% filter(Descript=="STOLEN TRAILER"|Descript=="VEHICLE, RECOVERED, MOBILE HOME-TRAILER" )
SFPD_stolen_other <- SFPD_vehicle_theft %>% filter(Descript=="STOLEN MOTORCYCLE"| Descript=="STOLEN MOTORCYCLE")
SFPD_stolen_bus <- SFPD_vehicle_theft %>% filter(Descript=="STOLEN BUS" | Descript=="VEHICLE, RECOVERED, BUS" )
SFPD_stolen_auto$vehicle_type= 'auto'
SFPD_stolen_bus$vehicle_type='bus'
SFPD_stolen_other$vehicle_type='other'
SFPD_stolen_motorcycle$vehicle_type='motorcycle'
SFPD_stolen_trailer$vehicle_type='trailer'
SFPD_stolen_truck$vehicle_type='truck'
SFPD_type_vehicle <- rbind(SFPD_stolen_auto, SFPD_stolen_bus, SFPD_stolen_other, SFPD_stolen_motorcycle, SFPD_stolen_trailer, SFPD_stolen_truck)
SFPD_recovered_vehicle <- SFPD_vehicle_theft %>% filter(Descript=="VEHICLE, RECOVERED, BUS" |Descript=="VEHICLE, RECOVERED, CAMPER-HOUSE CAR-MOTOR HOME" |Descript=="RECOVERED VEHICLE - STOLEN OUTSIDE SF" | Descript=="VEHICLE, RECOVERED, MOBILE HOME-TRAILER"|Descript=="VEHICLE, RECOVERED, AUTO" |Descript=="VEHICLE, RECOVERED, MOTORCYCLE" |Descript=="VEHICLE, RECOVERED, OTHER VEHICLE")
SFPD_stolen_vehicle$Recovery= 'No'
SFPD_recovered_vehicle$Recovery='Yes'
SFPD_recovery_data<- rbind(SFPD_stolen_vehicle,SFPD_recovered_vehicle)
Fig 3.1 and Fig 3.2
library(VIM)
Loading required package: colorspace
Loading required package: grid
Loading required package: data.table
data.table 1.10.4
The fastest way to learn (by data.table authors): https://www.datacamp.com/courses/data-analysis-the-data-table-way
Documentation: ?data.table, example(data.table) and browseVignettes("data.table")
Release notes, videos and slides: http://r-datatable.com
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
data.table + dplyr code now lives in dtplyr.
Please library(dtplyr)!
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Attaching package: ‘data.table’
The following objects are masked from ‘package:dplyr’:
between, first, last
VIM is ready to use.
Since version 4.0.0 the GUI is in its own package VIMGUI.
Please use the package to use the new (and old) GUI.
Suggestions and bug-reports can be submitted at: https://github.com/alexkowa/VIM/issues
Attaching package: ‘VIM’
The following object is masked from ‘package:datasets’:
sleep
a<-aggr(SFPD, bars=TRUE, delimiter = NULL, plot = TRUE)

summary(a)
Missings per variable:
Variable Count
IncidntNum 0
Category 0
Descript 0
DayOfWeek 0
Date 0
Time 0
PdDistrict 1
Resolution 0
Address 0
X 0
Y 0
Location 0
PdId 0
Year 0
Missings in combinations of variables:
Combinations Count Percent
0:0:0:0:0:0:0:0:0:0:0:0:0:0 1727399 9.999994e+01
0:0:0:0:0:0:1:0:0:0:0:0:0:0 1 5.789047e-05
matrixplot(SFPD,delimiter = NULL, fixup=FALSE,col = c("blue", "green"))
NAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercionNAs introduced by coercion
Fig 3.3
#reorder(Category, Category ,function(x)+length(x) )
p <- ggplot(SFPD_1 , aes( group=reorder(Category, Category ,function(x)+length(x) ),x = Year, colour= reorder(Category, Category ,function(x)+length(x) ))) +geom_path(stat ='count') +xlab('Year')+ ylab('Trend of Crime Reports') + ggtitle('Count of Crime reports over the years')+scale_fill_discrete(name = "Category")
p

fig 3.4
p <- ggplot(SFPD, aes( group=reorder(Resolution, Resolution ,function(x)+length(x) ), x= Resolution)) +geom_bar(stat ='count') +xlab('Resolution')+theme(axis.text.x = element_text(angle = 90, hjust = 1))
p

SFPD_2 <- SFPD %>% mutate(Month = (format(as.Date(Date, format="%d/%m/%Y"),"%m")))
SFPD_2 <- SFPD_2 %>% mutate(date= (format(as.Date(Date, format="%d/%m/%Y"),"%d")))
fig 3.5
p <- ggplot(SFPD_2, aes( x= date)) +geom_bar(stat ='count') +xlab('Dates') +facet_wrap(~Month)
p

Fig 3.6
mapgilbert <- get_map(location = c(lon = mean(SFPD$X), lat = mean(SFPD$Y)), zoom = 12,
maptype = "roadmap", scale = 2)
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=37.770958,-122.423016&zoom=12&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false
# plotting the map with some points on it
ggmap(mapgilbert) +
geom_point(data = SFPD, aes(x = X, y = Y, fill = "red", alpha = 0.8, colour= PdDistrict), size = 0.5, shape = 21 ) + geom_point(data = SFPD_vehicle_theft, aes(x = X, y = Y, alpha = 0.8, colour= PdDistrict), size = 1, shape = 21 )+
guides(fill=FALSE, alpha=FALSE, size=FALSE)

The plots below are in order as are in the Vehicle theft section.
#reorder(Category, Category ,function(x)+length(x) )
p <- ggplot(SFPD_vehicle_theft , aes( group=reorder(Category, Category ,function(x)+length(x) ),x = Year)) +geom_path(stat ='count') +xlab('Year')+ ylab('Trend of Vehicle Theft') + ggtitle('Count of vehicle theft over the years')+scale_fill_discrete(name = "Category")
p

p <- ggplot(SFPD_vehicle_theft , aes(group= Category , x= Month , )) +geom_line(stat='count') +xlab('Month') +facet_wrap(~Year)+ylab("Count of vehicle theft ")
p

#reorder(Category, Category ,function(x)+length(x) )
p <- ggplot(SFPD_vehicle_theft , aes( group=reorder(Category, Category ,function(x)+length(x) ),x = Month)) +geom_path(stat ='count') +xlab('Month of Year')+ylab("Count of vehicle theft")+ ggtitle("Trend of vehicle theft for different months")
p

day <- factor(SFPD_vehicle_theft$DayOfWeek, c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))
p <- ggplot(SFPD_vehicle_theft, aes(group= day , x= PdDistrict, fill=day)) +geom_bar(stat='count', position="dodge") +xlab('Police department district')+scale_fill_viridis(name="Day of Week", discrete = T)
p

p <- ggplot(SFPD_vehicle_theft , aes( group= Category , x= Hour)) +geom_path(stat='count') +xlab('Hour of Day')+ylab("Count of Vehicle theft reports")
p

p <- ggplot(SFPD_vehicle_theft , aes( x = reorder(Descript, Descript, function(x)+length(x)))) +geom_bar(stat ='count') +xlab('Description of Vehicle theft in report') +theme(axis.text.x = element_text(angle = 90, hjust = 1)) +coord_flip() + ylab("Count of Vehicle theft")+ ggtitle("Bar plot for description of vehicle theft")
p

p <- ggplot(SFPD_type_vehicle , aes( group= vehicle_type , x=Year, colour= vehicle_type)) +geom_path(stat='count') +xlab('Year')+ylab("Count of vehicle theft for different type of vehicles")+scale_color_viridis(name="Vehicle Type", discrete = T)
p

p <- ggplot(SFPD_vehicle_theft, aes( group=reorder(Resolution, Resolution ,function(x)+length(x) ), x= Resolution)) +geom_bar(stat ='count') +xlab('Resolution')+theme(axis.text.x = element_text(angle = 90, hjust = 1))
p

ggplot(SFPD_vehicle_theft , aes(x=reorder(PdDistrict, PdDistrict, function(x)+length(x)))) +geom_bar(stat='count') + xlab('Police department District') + ylab('count of crime')

map_SF_stolen_vehicle <- get_map(location = "San Francisco", zoom = 12, maptype = "roadmap", scale = 2)
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=San+Francisco&zoom=12&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false
Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=San%20Francisco&sensor=false
p<-ggmap(map_SF_stolen_vehicle) + geom_density2d(data = SFPD_vehicle_theft,
aes(x = X, y = Y), size = 0.3) + stat_density2d(data = SFPD_vehicle_theft,
aes(x = X, y = Y, fill = ..level.., alpha = ..level..), size = 0.01,
bins = 16, geom = "polygon") + scale_fill_viridis() +
scale_alpha(range = c(0, 0.3), guide = FALSE)
p

map_SF_stolen_vehicle <- get_map(location = "San Francisco", zoom = 12, maptype = "roadmap", scale = 2)
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=San+Francisco&zoom=12&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false
Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=San%20Francisco&sensor=false
p<-ggmap(map_SF_stolen_vehicle) + geom_density2d(data = SFPD_recovery_data,
aes(x = X, y = Y), size = 0.3) + stat_density2d(data = SFPD_recovery_data,
aes(x = X, y = Y, fill = ..level.., alpha = ..level..), size = 0.01,
bins = 16, geom = "polygon") + scale_fill_viridis() +
scale_alpha(range = c(0, 0.3), guide = FALSE) + facet_grid(~Recovery)
p

map_stolen_outside <- get_map(location = "San Francisco", zoom = 13, maptype = "roadmap", scale = 2)
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=San+Francisco&zoom=13&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false
Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=San%20Francisco&sensor=false
p<-ggmap(map_stolen_outside) + geom_density2d(data = SFPD_stolen_outside,
aes(x = X, y = Y), size = 0.3) + stat_density2d(data = SFPD_stolen_outside,
aes(x = X, y = Y, fill = ..level.., alpha = ..level..), size = 0.01,
bins = 16, geom = "polygon") + scale_fill_viridis() +
scale_alpha(range = c(0, 0.3), guide = FALSE) +ggtitle("Recovery of Vehicle stolen outside SF")
p

map_tampering <- get_map(location = "San Francisco car rentals", zoom = 13, maptype = "roadmap", scale = 2)
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=San+Francisco+car+rentals&zoom=13&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false
Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=San%20Francisco%20car%20rentals&sensor=false
p<-ggmap(map_tampering) + geom_density2d(data = SFPD_tampering,
aes(x = X, y = Y), size = 0.3) + stat_density2d(data = SFPD_tampering,
aes(x = X, y = Y, fill = ..level.., alpha = ..level..), size = 0.01,
bins = 16, geom = "polygon") + scale_fill_viridis() +
scale_alpha(range = c(0, 0.3), guide = FALSE)+ ggtitle("Tampering with the Vehicles")
p

map_stolen_outside <- get_map(location = "San Francisco", zoom = 13, maptype = "roadmap", scale = 2)
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=San+Francisco&zoom=13&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false
Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=San%20Francisco&sensor=false
p<-ggmap(map_stolen_outside) + geom_density2d(data = SFPD_type_vehicle,
aes(x = X, y = Y), size = 0.3) + stat_density2d(data = SFPD_type_vehicle,
aes(x = X, y = Y, fill = ..level.., alpha = ..level..), size = 0.01,
bins = 16, geom = "polygon") + scale_fill_viridis() +
scale_alpha(range = c(0, 0.3), guide = FALSE)+facet_wrap(~vehicle_type)
p

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0aWR5cikKbGlicmFyeShyZWFkcikKbGlicmFyeSh2aXJpZGlzKQpsaWJyYXJ5KGdnbWFwKQpsaWJyYXJ5KGdnbW9zYWljKQpgYGAKCgpgYGB7ciwgcmVzdWx0cz0naGlkZSd9ClNGUEQgPC0gcmVhZF9jc3YoIlNGUERfSW5jaWRlbnRzXy1fZnJvbV8xX0phbnVhcnlfMjAwMy5jc3YiLCAKIGNvbF90eXBlcyA9IGNvbHMoRGF0ZSA9IGNvbF9kYXRlKGZvcm1hdCA9ICIlbS8lZC8lWSIpLCBUaW1lPSBjb2xfY2hhcmFjdGVyKCkpKQpTRlBEIDwtIFNGUEQgW29yZGVyKFNGUEQkRGF0ZSksXQpTRlBEIDwtIFNGUEQgJT4lIGZpbHRlciggQ2F0ZWdvcnkgIT0gJ09USEVSIE9GRkVOU0VTJyApClNGUERfMSA8LSBTRlBEICU+JSBtdXRhdGUoWWVhciA9IChmb3JtYXQoYXMuRGF0ZShEYXRlLCBmb3JtYXQ9IiVkLyVtLyVZIiksIiVZIikpKQoKU0ZQRCA8LSBTRlBEXzEgJT4lIGZpbHRlciggWWVhciAhPSAyMDE3ICkKU0ZQRF90b3A3IDwtIFNGUEQgJT4lIGZpbHRlcihDYXRlZ29yeSA9PSAnTEFSQ0VOWS9USEVGVCd8IENhdGVnb3J5ID09ICdOT04tQ1JJTUlOQUwnfCBDYXRlZ29yeSA9PSAnQVNTQVVMVCd8ICBDYXRlZ29yeSA9PSAnVkVISUNMRSBUSEVGVCd8ICBDYXRlZ29yeSA9PSAnRFJVRy9OQVJDT1RJQyd8IENhdGVnb3J5ID09J1ZBTkRBTElTTSd8IENhdGVnb3J5ID09ICdXQVJSQU5UUyd8IENhdGVnb3J5ID09ICdCVVJHTEFSWSd8IENhdGVnb3J5ID09J1NVU1BJQ0lPVVMgT0NDJ3wgQ2F0ZWdvcnkgPT0nTUlTU0lORyBQRVJTT04nIHwgQ2F0ZWdvcnkgPT0nUk9CQkVSWScgfCBDYXRlZ29yeSA9PSdGUkFVRCcgKQoKU0ZQRF92ZWhpY2xlX3RoZWZ0IDwtIFNGUERfdG9wNyAlPiUgZmlsdGVyKENhdGVnb3J5ID09ICdWRUhJQ0xFIFRIRUZUJykKClNGUERfdmVoaWNsZV90aGVmdCA8LSBTRlBEX3ZlaGljbGVfdGhlZnQgJT4lIG11dGF0ZShNb250aCA9IChmb3JtYXQoYXMuRGF0ZShEYXRlLCBmb3JtYXQ9IiVkLyVtLyVZIiksIiVtIikpKQpTRlBEX3ZlaGljbGVfdGhlZnQgPC0gU0ZQRF92ZWhpY2xlX3RoZWZ0ICU+JSBtdXRhdGUoZGF0ZT0gKGZvcm1hdChhcy5EYXRlKERhdGUsIGZvcm1hdD0iJWQvJW0vJVkiKSwiJWQiKSkpClNGUERfdmVoaWNsZV90aGVmdCA8LSBTRlBEX3ZlaGljbGVfdGhlZnQgJT4lIG11dGF0ZShIb3VyPSBmb3JtYXQoYXMuUE9TSVhjdChUaW1lLGZvcm1hdD0iJUg6JU0iKSwiJUgiKSkKU0ZQRF9WVF9vY3RfaW5nbGVzaWRlIDwtIFNGUERfdmVoaWNsZV90aGVmdCAlPiUgZmlsdGVyKE1vbnRoID09IDEwICYgUGREaXN0cmljdD09ICdJTkdMRVNJREUnKQoKU0ZQRF9WVF9vY3RfaW5nbGVzaWRlIDwtIFNGUERfVlRfb2N0X2luZ2xlc2lkZSAlPiUgbXV0YXRlKGRhdGU9IChmb3JtYXQoYXMuRGF0ZShEYXRlLCBmb3JtYXQ9IiVkLyVtLyVZIiksIiVkIikpKQoKCmBgYAoKCgpgYGB7cn0KU0ZQRF9zdG9sZW5fdmVoaWNsZSA8LSBTRlBEX3ZlaGljbGVfdGhlZnQgJT4lIGZpbHRlcihEZXNjcmlwdD09IlNUT0xFTiBBVVRPTU9CSUxFIiB8IERlc2NyaXB0PT0iU1RPTEVOIFRSQUlMRVIiIHxEZXNjcmlwdD09IlNUT0xFTiBUUlVDSyJ8RGVzY3JpcHQ9PSJTVE9MRU4gQlVTIiB8RGVzY3JpcHQ9PSJTVE9MRU4gTUlTQ0VMTEFORU9VUyBWRUhJQ0xFIiB8RGVzY3JpcHQ9PSJTVE9MRU4gTU9UT1JDWUNMRSIpCgpTRlBEX3JlY292ZXJlZF92ZWhpY2xlIDwtIFNGUERfdmVoaWNsZV90aGVmdCAlPiUgZmlsdGVyKERlc2NyaXB0PT0iVkVISUNMRSwgUkVDT1ZFUkVELCBCVVMiIHxEZXNjcmlwdD09IlZFSElDTEUsIFJFQ09WRVJFRCwgQ0FNUEVSLUhPVVNFIENBUi1NT1RPUiBIT01FIiB8RGVzY3JpcHQ9PSJSRUNPVkVSRUQgVkVISUNMRSAtIFNUT0xFTiBPVVRTSURFIFNGIiB8IERlc2NyaXB0PT0iVkVISUNMRSwgUkVDT1ZFUkVELCBNT0JJTEUgSE9NRS1UUkFJTEVSInxEZXNjcmlwdD09IlZFSElDTEUsIFJFQ09WRVJFRCwgQVVUTyIgfERlc2NyaXB0PT0iVkVISUNMRSwgUkVDT1ZFUkVELCBNT1RPUkNZQ0xFIiB8RGVzY3JpcHQ9PSJWRUhJQ0xFLCBSRUNPVkVSRUQsIE9USEVSIFZFSElDTEUiKQoKU0ZQRF9zdG9sZW5fb3V0c2lkZTwtIFNGUERfdmVoaWNsZV90aGVmdCAlPiUgZmlsdGVyKERlc2NyaXB0PT0gIlJFQ09WRVJFRCBWRUhJQ0xFIC0gU1RPTEVOIE9VVFNJREUgU0YiICkKU0ZQRF90YW1wZXJpbmcgPC0gU0ZQRF92ZWhpY2xlX3RoZWZ0ICU+JSBmaWx0ZXIoRGVzY3JpcHQ9PSJUQU1QRVJJTkcgV0lUSCBBIFZFSElDTEUiICkKCmBgYAoKYGBge3J9ClNGUERfc3RvbGVuX2F1dG8gPC0gU0ZQRF92ZWhpY2xlX3RoZWZ0ICU+JSBmaWx0ZXIoRGVzY3JpcHQ9PSJTVE9MRU4gQVVUT01PQklMRSJ8RGVzY3JpcHQ9PSJWRUhJQ0xFLCBSRUNPVkVSRUQsIEFVVE8iICApClNGUERfc3RvbGVuX3RydWNrIDwtIFNGUERfdmVoaWNsZV90aGVmdCAlPiUgZmlsdGVyKERlc2NyaXB0PT0iU1RPTEVOIFRSVUNLInxEZXNjcmlwdD09IlZFSElDTEUsIFJFQ09WRVJFRCwgQlVTIiAgKQoKU0ZQRF9zdG9sZW5fbW90b3JjeWNsZSA8LSBTRlBEX3ZlaGljbGVfdGhlZnQgJT4lIGZpbHRlcihEZXNjcmlwdD09IlNUT0xFTiBNT1RPUkNZQ0xFInxEZXNjcmlwdD09IlZFSElDTEUsIFJFQ09WRVJFRCwgTU9UT1JDWUNMRSIgICkKClNGUERfc3RvbGVuX3RyYWlsZXIgPC0gU0ZQRF92ZWhpY2xlX3RoZWZ0ICU+JSBmaWx0ZXIoRGVzY3JpcHQ9PSJTVE9MRU4gVFJBSUxFUiJ8RGVzY3JpcHQ9PSJWRUhJQ0xFLCBSRUNPVkVSRUQsIE1PQklMRSBIT01FLVRSQUlMRVIiICkKClNGUERfc3RvbGVuX290aGVyIDwtIFNGUERfdmVoaWNsZV90aGVmdCAlPiUgZmlsdGVyKERlc2NyaXB0PT0iU1RPTEVOIE1PVE9SQ1lDTEUifCBEZXNjcmlwdD09IlNUT0xFTiBNT1RPUkNZQ0xFIikKClNGUERfc3RvbGVuX2J1cyA8LSBTRlBEX3ZlaGljbGVfdGhlZnQgJT4lIGZpbHRlcihEZXNjcmlwdD09IlNUT0xFTiBCVVMiIHwgRGVzY3JpcHQ9PSJWRUhJQ0xFLCBSRUNPVkVSRUQsIEJVUyIgKQoKU0ZQRF9zdG9sZW5fYXV0byR2ZWhpY2xlX3R5cGU9ICdhdXRvJyAKU0ZQRF9zdG9sZW5fYnVzJHZlaGljbGVfdHlwZT0nYnVzJwpTRlBEX3N0b2xlbl9vdGhlciR2ZWhpY2xlX3R5cGU9J290aGVyJwpTRlBEX3N0b2xlbl9tb3RvcmN5Y2xlJHZlaGljbGVfdHlwZT0nbW90b3JjeWNsZScKU0ZQRF9zdG9sZW5fdHJhaWxlciR2ZWhpY2xlX3R5cGU9J3RyYWlsZXInClNGUERfc3RvbGVuX3RydWNrJHZlaGljbGVfdHlwZT0ndHJ1Y2snCgpTRlBEX3R5cGVfdmVoaWNsZSA8LSByYmluZChTRlBEX3N0b2xlbl9hdXRvLCBTRlBEX3N0b2xlbl9idXMsIFNGUERfc3RvbGVuX290aGVyLCBTRlBEX3N0b2xlbl9tb3RvcmN5Y2xlLCBTRlBEX3N0b2xlbl90cmFpbGVyLCBTRlBEX3N0b2xlbl90cnVjaykKICAKICAKClNGUERfcmVjb3ZlcmVkX3ZlaGljbGUgPC0gU0ZQRF92ZWhpY2xlX3RoZWZ0ICU+JSBmaWx0ZXIoRGVzY3JpcHQ9PSJWRUhJQ0xFLCBSRUNPVkVSRUQsIEJVUyIgfERlc2NyaXB0PT0iVkVISUNMRSwgUkVDT1ZFUkVELCBDQU1QRVItSE9VU0UgQ0FSLU1PVE9SIEhPTUUiIHxEZXNjcmlwdD09IlJFQ09WRVJFRCBWRUhJQ0xFIC0gU1RPTEVOIE9VVFNJREUgU0YiIHwgRGVzY3JpcHQ9PSJWRUhJQ0xFLCBSRUNPVkVSRUQsIE1PQklMRSBIT01FLVRSQUlMRVIifERlc2NyaXB0PT0iVkVISUNMRSwgUkVDT1ZFUkVELCBBVVRPIiB8RGVzY3JpcHQ9PSJWRUhJQ0xFLCBSRUNPVkVSRUQsIE1PVE9SQ1lDTEUiIHxEZXNjcmlwdD09IlZFSElDTEUsIFJFQ09WRVJFRCwgT1RIRVIgVkVISUNMRSIpCmBgYAoKCmBgYHtyfQpTRlBEX3N0b2xlbl92ZWhpY2xlJFJlY292ZXJ5PSAnTm8nClNGUERfcmVjb3ZlcmVkX3ZlaGljbGUkUmVjb3Zlcnk9J1llcycKClNGUERfcmVjb3ZlcnlfZGF0YTwtIHJiaW5kKFNGUERfc3RvbGVuX3ZlaGljbGUsU0ZQRF9yZWNvdmVyZWRfdmVoaWNsZSkKYGBgCgojI0ZpZyAzLjEgYW5kIEZpZyAzLjIKCmBgYHtyfQoKbGlicmFyeShWSU0pCmE8LWFnZ3IoU0ZQRCwgYmFycz1UUlVFLCBkZWxpbWl0ZXIgPSBOVUxMLCBwbG90ID0gVFJVRSkKc3VtbWFyeShhKQptYXRyaXhwbG90KFNGUEQsZGVsaW1pdGVyID0gTlVMTCwgZml4dXA9RkFMU0UsY29sID0gYygiYmx1ZSIsICJncmVlbiIpKQpoZWFkKHNjb3JlY2FyZCkKYGBgCgoKIyMgRmlnIDMuMwoKYGBge3IsICBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xNX0KI3Jlb3JkZXIoQ2F0ZWdvcnksIENhdGVnb3J5ICxmdW5jdGlvbih4KStsZW5ndGgoeCkgKQpwIDwtIGdncGxvdChTRlBEXzEgLCBhZXMoIGdyb3VwPXJlb3JkZXIoQ2F0ZWdvcnksIENhdGVnb3J5ICxmdW5jdGlvbih4KStsZW5ndGgoeCkgKSx4ID0gWWVhciwgY29sb3VyPSByZW9yZGVyKENhdGVnb3J5LCBDYXRlZ29yeSAsZnVuY3Rpb24oeCkrbGVuZ3RoKHgpICkpKSArZ2VvbV9wYXRoKHN0YXQgPSdjb3VudCcpICAreGxhYignWWVhcicpKyB5bGFiKCdUcmVuZCBvZiBDcmltZSBSZXBvcnRzJykgKyBnZ3RpdGxlKCdDb3VudCBvZiBDcmltZSAgcmVwb3J0cyBvdmVyIHRoZSB5ZWFycyBpbmNsdWRpbmcgMjAxNycpK3NjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJDYXRlZ29yeSIpCgoKcCAKYGBgCgojI2ZpZyAzLjQKCmBgYHtyLCAgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTB9CnAgPC0gZ2dwbG90KFNGUEQsIGFlcyggZ3JvdXA9cmVvcmRlcihSZXNvbHV0aW9uLCBSZXNvbHV0aW9uICxmdW5jdGlvbih4KStsZW5ndGgoeCkgKSwgeD0gUmVzb2x1dGlvbikpICtnZW9tX2JhcihzdGF0ID0nY291bnQnKSAgK3hsYWIoJ1Jlc29sdXRpb24nKSt0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKSAKcApgYGAKCgpgYGB7cn0KU0ZQRF8yIDwtIFNGUEQgJT4lIG11dGF0ZShNb250aCA9IChmb3JtYXQoYXMuRGF0ZShEYXRlLCBmb3JtYXQ9IiVkLyVtLyVZIiksIiVtIikpKQpTRlBEXzIgPC0gU0ZQRF8yICU+JSBtdXRhdGUoZGF0ZT0gKGZvcm1hdChhcy5EYXRlKERhdGUsIGZvcm1hdD0iJWQvJW0vJVkiKSwiJWQiKSkpCmBgYAoKCiMjZmlnIDMuNQoKYGBge3IsICBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0yMH0KcCA8LSBnZ3Bsb3QoU0ZQRF8yLCBhZXMoICB4PSBkYXRlKSkgK2dlb21fYmFyKHN0YXQgPSdjb3VudCcpICAreGxhYignRGF0ZXMnKSArZmFjZXRfd3JhcCh+TW9udGgpCnAKYGBgCgoKCiMjIEZpZyAzLjYKYGBge3IsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0yMH0KbWFwZ2lsYmVydCA8LSBnZXRfbWFwKGxvY2F0aW9uID0gYyhsb24gPSBtZWFuKFNGUEQkWCksIGxhdCA9IG1lYW4oU0ZQRCRZKSksIHpvb20gPSAxMiwKICAgICAgICAgICAgICAgICAgICAgIG1hcHR5cGUgPSAicm9hZG1hcCIsIHNjYWxlID0gMikKCiMgcGxvdHRpbmcgdGhlIG1hcCB3aXRoIHNvbWUgcG9pbnRzIG9uIGl0CmdnbWFwKG1hcGdpbGJlcnQpICsKICBnZW9tX3BvaW50KGRhdGEgPSBTRlBELCBhZXMoeCA9IFgsIHkgPSBZLCBmaWxsID0gInJlZCIsIGFscGhhID0gMC44LCBjb2xvdXI9IFBkRGlzdHJpY3QpLCBzaXplID0gMC41LCBzaGFwZSA9IDIxICkgICsgZ2VvbV9wb2ludChkYXRhID0gU0ZQRF92ZWhpY2xlX3RoZWZ0LCBhZXMoeCA9IFgsIHkgPSBZLCBhbHBoYSA9IDAuOCwgY29sb3VyPSBQZERpc3RyaWN0KSwgc2l6ZSA9IDEsIHNoYXBlID0gMjEgKSsKICBndWlkZXMoZmlsbD1GQUxTRSwgYWxwaGE9RkFMU0UsIHNpemU9RkFMU0UpCmBgYAoKIyNUaGUgcGxvdHMgYmVsb3cgYXJlIGluIG9yZGVyIGFzIGFyZSBpbiB0aGUgVmVoaWNsZSB0aGVmdCBzZWN0aW9uLgoKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTE1fQojcmVvcmRlcihDYXRlZ29yeSwgQ2F0ZWdvcnkgLGZ1bmN0aW9uKHgpK2xlbmd0aCh4KSApCnAgPC0gZ2dwbG90KFNGUERfdmVoaWNsZV90aGVmdCAsIGFlcyggZ3JvdXA9cmVvcmRlcihDYXRlZ29yeSwgQ2F0ZWdvcnkgLGZ1bmN0aW9uKHgpK2xlbmd0aCh4KSApLHggPSBZZWFyKSkgK2dlb21fcGF0aChzdGF0ID0nY291bnQnKSAgK3hsYWIoJ1llYXInKSsgeWxhYignVHJlbmQgb2YgVmVoaWNsZSBUaGVmdCcpICsgZ2d0aXRsZSgnQ291bnQgb2YgdmVoaWNsZSB0aGVmdCBvdmVyIHRoZSB5ZWFycycpK3NjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJDYXRlZ29yeSIpCgoKcCAKYGBgCmBgYHtyLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CnAgPC0gZ2dwbG90KFNGUERfdmVoaWNsZV90aGVmdCAsIGFlcyhncm91cD0gQ2F0ZWdvcnkgLCB4PSBNb250aCAsICkpICtnZW9tX2xpbmUoc3RhdD0nY291bnQnKSAreGxhYignTW9udGgnKSArZmFjZXRfd3JhcCh+WWVhcikreWxhYigiQ291bnQgb2YgdmVoaWNsZSB0aGVmdCAiKQpwIApgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xNX0KI3Jlb3JkZXIoQ2F0ZWdvcnksIENhdGVnb3J5ICxmdW5jdGlvbih4KStsZW5ndGgoeCkgKQpwIDwtIGdncGxvdChTRlBEX3ZlaGljbGVfdGhlZnQgLCBhZXMoIGdyb3VwPXJlb3JkZXIoQ2F0ZWdvcnksIENhdGVnb3J5ICxmdW5jdGlvbih4KStsZW5ndGgoeCkgKSx4ID0gTW9udGgpKSArZ2VvbV9wYXRoKHN0YXQgPSdjb3VudCcpICAreGxhYignTW9udGggb2YgWWVhcicpK3lsYWIoIkNvdW50IG9mIHZlaGljbGUgdGhlZnQiKSsgZ2d0aXRsZSgiVHJlbmQgb2YgdmVoaWNsZSB0aGVmdCBmb3IgZGlmZmVyZW50IG1vbnRocyIpCnAgCmBgYAoKCgoKCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQpkYXkgPC0gZmFjdG9yKFNGUERfdmVoaWNsZV90aGVmdCREYXlPZldlZWssIGMoIk1vbmRheSIsICJUdWVzZGF5IiwgIldlZG5lc2RheSIsICJUaHVyc2RheSIsICJGcmlkYXkiLCAiU2F0dXJkYXkiLCAiU3VuZGF5IikpCnAgPC0gZ2dwbG90KFNGUERfdmVoaWNsZV90aGVmdCwgYWVzKGdyb3VwPSBkYXkgLCB4PSBQZERpc3RyaWN0LCBmaWxsPWRheSkpICtnZW9tX2JhcihzdGF0PSdjb3VudCcsIHBvc2l0aW9uPSJkb2RnZSIpICt4bGFiKCdQb2xpY2UgZGVwYXJ0bWVudCBkaXN0cmljdCcpK3NjYWxlX2ZpbGxfdmlyaWRpcyhuYW1lPSJEYXkgb2YgV2VlayIsIGRpc2NyZXRlID0gVCkgCnAKCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KcCA8LSBnZ3Bsb3QoU0ZQRF92ZWhpY2xlX3RoZWZ0ICwgYWVzKCBncm91cD0gQ2F0ZWdvcnkgLCB4PSBIb3VyKSkgK2dlb21fcGF0aChzdGF0PSdjb3VudCcpICAreGxhYignSG91ciBvZiBEYXknKSt5bGFiKCJDb3VudCBvZiBWZWhpY2xlIHRoZWZ0IHJlcG9ydHMiKQpwCgpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xNX0KcCA8LSBnZ3Bsb3QoU0ZQRF92ZWhpY2xlX3RoZWZ0ICwgYWVzKCB4ID0gcmVvcmRlcihEZXNjcmlwdCwgRGVzY3JpcHQsIGZ1bmN0aW9uKHgpK2xlbmd0aCh4KSkpKSArZ2VvbV9iYXIoc3RhdCA9J2NvdW50JykgICt4bGFiKCdEZXNjcmlwdGlvbiBvZiBWZWhpY2xlIHRoZWZ0IGluIHJlcG9ydCcpICt0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKSArY29vcmRfZmxpcCgpICsgeWxhYigiQ291bnQgb2YgVmVoaWNsZSB0aGVmdCIpKyBnZ3RpdGxlKCJCYXIgcGxvdCBmb3IgZGVzY3JpcHRpb24gb2YgdmVoaWNsZSB0aGVmdCIpCnAgCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEzfQpwIDwtIGdncGxvdChTRlBEX3R5cGVfdmVoaWNsZSAsIGFlcyggZ3JvdXA9IHZlaGljbGVfdHlwZSAsIHg9WWVhciwgY29sb3VyPSB2ZWhpY2xlX3R5cGUpKSArZ2VvbV9wYXRoKHN0YXQ9J2NvdW50JykgICt4bGFiKCdZZWFyJykreWxhYigiQ291bnQgb2YgdmVoaWNsZSB0aGVmdCBmb3IgZGlmZmVyZW50IHR5cGUgb2YgdmVoaWNsZXMiKStzY2FsZV9jb2xvcl92aXJpZGlzKG5hbWU9IlZlaGljbGUgVHlwZSIsIGRpc2NyZXRlID0gVCkKcApgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwfQpwIDwtIGdncGxvdChTRlBEX3ZlaGljbGVfdGhlZnQsIGFlcyggZ3JvdXA9cmVvcmRlcihSZXNvbHV0aW9uLCBSZXNvbHV0aW9uICxmdW5jdGlvbih4KStsZW5ndGgoeCkgKSwgeD0gUmVzb2x1dGlvbikpICtnZW9tX2JhcihzdGF0ID0nY291bnQnKSAgK3hsYWIoJ1Jlc29sdXRpb24nKSt0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKSAKcCAKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwfQpnZ3Bsb3QoU0ZQRF92ZWhpY2xlX3RoZWZ0ICwgYWVzKHg9cmVvcmRlcihQZERpc3RyaWN0LCBQZERpc3RyaWN0LCBmdW5jdGlvbih4KStsZW5ndGgoeCkpKSkgK2dlb21fYmFyKHN0YXQ9J2NvdW50JykgICsgeGxhYignUG9saWNlIGRlcGFydG1lbnQgRGlzdHJpY3QnKSArIHlsYWIoJ2NvdW50IG9mIGNyaW1lJykgIApgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTIwfQptYXBfU0Zfc3RvbGVuX3ZlaGljbGUgPC0gZ2V0X21hcChsb2NhdGlvbiA9ICJTYW4gRnJhbmNpc2NvIiwgem9vbSA9IDEyLCBtYXB0eXBlID0gInJvYWRtYXAiLCBzY2FsZSA9IDIpCnA8LWdnbWFwKG1hcF9TRl9zdG9sZW5fdmVoaWNsZSkgKyBnZW9tX2RlbnNpdHkyZChkYXRhID0gU0ZQRF92ZWhpY2xlX3RoZWZ0LAogICBhZXMoeCA9IFgsIHkgPSBZKSwgc2l6ZSA9IDAuMykgKyBzdGF0X2RlbnNpdHkyZChkYXRhID0gU0ZQRF92ZWhpY2xlX3RoZWZ0LAogICBhZXMoeCA9IFgsIHkgPSBZLCBmaWxsID0gLi5sZXZlbC4uLCBhbHBoYSA9IC4ubGV2ZWwuLiksIHNpemUgPSAwLjAxLAogICBiaW5zID0gMTYsIGdlb20gPSAicG9seWdvbiIpICsgc2NhbGVfZmlsbF92aXJpZGlzKCkgKwogICBzY2FsZV9hbHBoYShyYW5nZSA9IGMoMCwgMC4zKSwgZ3VpZGUgPSBGQUxTRSkgCgpwCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MjB9Cm1hcF9TRl9zdG9sZW5fdmVoaWNsZSA8LSBnZXRfbWFwKGxvY2F0aW9uID0gIlNhbiBGcmFuY2lzY28iLCB6b29tID0gMTIsIG1hcHR5cGUgPSAicm9hZG1hcCIsIHNjYWxlID0gMikKcDwtZ2dtYXAobWFwX1NGX3N0b2xlbl92ZWhpY2xlKSArIGdlb21fZGVuc2l0eTJkKGRhdGEgPSBTRlBEX3JlY292ZXJ5X2RhdGEsCiAgIGFlcyh4ID0gWCwgeSA9IFkpLCBzaXplID0gMC4zKSArIHN0YXRfZGVuc2l0eTJkKGRhdGEgPSBTRlBEX3JlY292ZXJ5X2RhdGEsCiAgIGFlcyh4ID0gWCwgeSA9IFksIGZpbGwgPSAuLmxldmVsLi4sIGFscGhhID0gLi5sZXZlbC4uKSwgc2l6ZSA9IDAuMDEsCiAgIGJpbnMgPSAxNiwgZ2VvbSA9ICJwb2x5Z29uIikgKyBzY2FsZV9maWxsX3ZpcmlkaXMoKSArCiAgIHNjYWxlX2FscGhhKHJhbmdlID0gYygwLCAwLjMpLCBndWlkZSA9IEZBTFNFKSArIGZhY2V0X2dyaWQoflJlY292ZXJ5KSAKCnAKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwfQptYXBfc3RvbGVuX291dHNpZGUgPC0gZ2V0X21hcChsb2NhdGlvbiA9ICJTYW4gRnJhbmNpc2NvIiwgem9vbSA9IDEzLCBtYXB0eXBlID0gInJvYWRtYXAiLCBzY2FsZSA9IDIpCnA8LWdnbWFwKG1hcF9zdG9sZW5fb3V0c2lkZSkgKyBnZW9tX2RlbnNpdHkyZChkYXRhID0gU0ZQRF9zdG9sZW5fb3V0c2lkZSwKICAgYWVzKHggPSBYLCB5ID0gWSksIHNpemUgPSAwLjMpICsgc3RhdF9kZW5zaXR5MmQoZGF0YSA9IFNGUERfc3RvbGVuX291dHNpZGUsCiAgIGFlcyh4ID0gWCwgeSA9IFksIGZpbGwgPSAuLmxldmVsLi4sIGFscGhhID0gLi5sZXZlbC4uKSwgc2l6ZSA9IDAuMDEsCiAgIGJpbnMgPSAxNiwgZ2VvbSA9ICJwb2x5Z29uIikgKyBzY2FsZV9maWxsX3ZpcmlkaXMoKSArCiAgIHNjYWxlX2FscGhhKHJhbmdlID0gYygwLCAwLjMpLCBndWlkZSA9IEZBTFNFKSArZ2d0aXRsZSgiUmVjb3Zlcnkgb2YgVmVoaWNsZSBzdG9sZW4gb3V0c2lkZSBTRiIpCnAKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwfQptYXBfdGFtcGVyaW5nIDwtIGdldF9tYXAobG9jYXRpb24gPSAiU2FuIEZyYW5jaXNjbyIsIHpvb20gPSAxMywgbWFwdHlwZSA9ICJyb2FkbWFwIiwgc2NhbGUgPSAyKQpwPC1nZ21hcChtYXBfdGFtcGVyaW5nKSArIGdlb21fZGVuc2l0eTJkKGRhdGEgPSBTRlBEX3RhbXBlcmluZywKICAgYWVzKHggPSBYLCB5ID0gWSksIHNpemUgPSAwLjMpICsgc3RhdF9kZW5zaXR5MmQoZGF0YSA9IFNGUERfdGFtcGVyaW5nLAogICBhZXMoeCA9IFgsIHkgPSBZLCBmaWxsID0gLi5sZXZlbC4uLCBhbHBoYSA9IC4ubGV2ZWwuLiksIHNpemUgPSAwLjAxLAogICBiaW5zID0gMTYsIGdlb20gPSAicG9seWdvbiIpICsgc2NhbGVfZmlsbF92aXJpZGlzKCkgKwogICBzY2FsZV9hbHBoYShyYW5nZSA9IGMoMCwgMC4zKSwgZ3VpZGUgPSBGQUxTRSkrIGdndGl0bGUoIlRhbXBlcmluZyB3aXRoIHRoZSBWZWhpY2xlcyIpCnAKYGBgCgoKCgoKCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTIwfQptYXBfc3RvbGVuX291dHNpZGUgPC0gZ2V0X21hcChsb2NhdGlvbiA9ICJTYW4gRnJhbmNpc2NvIiwgem9vbSA9IDEzLCBtYXB0eXBlID0gInJvYWRtYXAiLCBzY2FsZSA9IDIpCnA8LWdnbWFwKG1hcF9zdG9sZW5fb3V0c2lkZSkgKyBnZW9tX2RlbnNpdHkyZChkYXRhID0gU0ZQRF90eXBlX3ZlaGljbGUsCiAgIGFlcyh4ID0gWCwgeSA9IFkpLCBzaXplID0gMC4zKSArIHN0YXRfZGVuc2l0eTJkKGRhdGEgPSBTRlBEX3R5cGVfdmVoaWNsZSwKICAgYWVzKHggPSBYLCB5ID0gWSwgZmlsbCA9IC4ubGV2ZWwuLiwgYWxwaGEgPSAuLmxldmVsLi4pLCBzaXplID0gMC4wMSwKICAgYmlucyA9IDE2LCBnZW9tID0gInBvbHlnb24iKSArIHNjYWxlX2ZpbGxfdmlyaWRpcygpICsKICAgc2NhbGVfYWxwaGEocmFuZ2UgPSBjKDAsIDAuMyksIGd1aWRlID0gRkFMU0UpK2ZhY2V0X3dyYXAofnZlaGljbGVfdHlwZSkKcApgYGAKCgoKCgoKCgoKCgo=